#ifndef MNG_DTOR_H
#define MNG_DTOR_H

#include <malloc.h>

#ifdef __cplusplus
extern "C" {
#endif

struct mng_dtor_list
{
	void *p;
	void (*dtor)(void *);
	struct mng_dtor_list *next;
};

typedef struct mng_dtor_list  mng_dtor_list;

struct mng_ctx
{
	mng_dtor_list *dtor_list;
};

typedef struct mng_ctx mng_ctx;

static void mng_set_dtor(mng_ctx* ctx, void *p, void (*dtor)(void *))
{
	mng_dtor_list *node;

	if (p != NULL && dtor != NULL)
	{
		node = (mng_dtor_list *)calloc(1, sizeof(mng_dtor_list));
		node->p = p;
		node->dtor = dtor;
		node->next = ctx->dtor_list;
		ctx->dtor_list = node;
	}
}

static void mng_clear_ctx(mng_ctx *ctx)
{
	mng_dtor_list *next;

	while (ctx->dtor_list != NULL)
	{
		next = ctx->dtor_list->next;
		ctx->dtor_list->dtor(ctx->dtor_list->p);
		free(ctx->dtor_list);
		ctx->dtor_list = next;
	}
}

#define mng_enter() mng_ctx mng_local_ctx = {0}
#define mng_on_leave(dtor, p) mng_set_dtor(&mng_local_ctx, (p), dtor)
#define mng_leave() mng_clear_ctx(&mng_local_ctx)

#define mng_clearable mng_ctx mng
#define mng_on_clear(owner, dtor, p) mng_set_dtor(&((owner)->mng), (p), dtor)
#define mng_clear(owner) mng_clear_ctx(&((owner)->mng))

#ifdef __cplusplus
}
#endif

#endif
